﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary.FFTPack
{
    /// <summary>
    /// Sine FFT transform with odd wave numbers. 
    /// </summary>
    [Serializable]
    public class RealDoubleFFTOddOdd : RealDoubleFFTEvenOdd
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="RealDoubleFFTOddOdd"/> class.
        /// </summary>
        /// <param name="n">The size of a real data sequence. When n is a multiplication of small 
        /// numbers (4, 2, 3, 5), this FFT transform is very efficient.</param>
        public RealDoubleFFTOddOdd(int n)
            : base(n)
        {
        }

        /// <summary>
        /// Forward FFT transform of quarter wave data. It computes the coeffients in sine series 
        /// representation with only odd wave numbers.
        /// </summary>
        /// <param name="x">An array which contains the sequence to be transformed. After FFT, x
        /// contains the transform coeffients.</param>
        public override void ForwardTransform(double[] x)
        {
            Sinqf(ndim, x, wavetable);
        }

        /// <summary>
        /// Backward FFT transform of quarter wave data. It is the unnormalized inverse transform of 
        /// forward transform.
        /// </summary>
        /// <param name="x">An array which contains the sequence to be transformed. After FFT, x
        /// contains the transform coeffients.</param>
        public override void BackTransform(double[] x)
        {
            Sinqb(ndim, x, wavetable);
        }

        private void Sinqf(int n, double[] x, double[] wtable)
        {
            int k;
            double xhold;
            int kc, ns2;

            if (n == 1)
            {
                return;
            }
            ns2 = n / 2;
            for (k = 0; k < ns2; k++)
            {
                kc = n - k - 1;
                xhold = x[k];
                x[k] = x[kc];
                x[kc] = xhold;
            }
            Cosqf(n, x, wtable);
            for (k = 1; k < n; k += 2)
            {
                x[k] = -x[k];
            }
        }

        private void Sinqb(int n, double[] x, double[] wtable)
        {
            int k;
            double xhold;
            int kc, ns2;

            if (n <= 1)
            {
                x[0] *= 4;
                return;
            }
            ns2 = n / 2;
            for (k = 1; k < n; k += 2)
            {
                x[k] = -x[k];
            }
            Cosqb(n, x, wtable);
            for (k = 0; k < ns2; k++)
            {
                kc = n - k - 1;
                xhold = x[k];
                x[k] = x[kc];
                x[kc] = xhold;
            }
        }
    }
}